package com.jjh.springframework.bean.factory.config;

import com.jjh.springframework.bean.BeansException;
import com.jjh.springframework.bean.factory.DisposableBean;
import com.jjh.springframework.bean.factory.support.DisposableBeanAdapter;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * DefaultSingletonBeanRegistry
 *在 DefaultSingletonBeanRegistry 中主要实现 getSingleton 方法，
 * 同时实现了一个受保护的 addSingleton 方法，这个方法可以被继承此类的其他类调用。
 * 包括：AbstractBeanFactory 以及继承的 DefaultListableBeanFactory 调用。
 * @author jjh
 * @date 2021/06/05
 **/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    protected static final Object NULL_OBJECT = new Object();

    private HashMap<String, Object> singletonObjects = new HashMap<String, Object>();

    private Map<String, DisposableBean> disposableBeans = new HashMap<>();

    @Override
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }

    @Override
    public void registerSingleton(String beanName, Object singletonObject) {
        addSingleton(beanName, singletonObject);
    }

    protected void addSingleton(String beanName, Object object) {
        singletonObjects.put(beanName, object);
    }

    public void registerDisposableBean(String beanName, DisposableBeanAdapter disposableBeanAdapter){
        disposableBeans.put(beanName, disposableBeanAdapter);
    }

    public void destroySingletons(){
        Set<String> beanNameSet = this.disposableBeans.keySet();
        Object[] disposableBeanNames = beanNameSet.toArray();
        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            Object disposableBeanName = disposableBeanNames[i];
            DisposableBean disposableBean = disposableBeans.remove(disposableBeanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + disposableBeanName + "' throw an exception", e);
            }
        }
    }
}
